using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Terra.Core.Common.ApiResponse;
using Terra.Core.Common.ErrorCodes.Constants;
using Terra.Core.Common.Utils;
using Terra.Core.Security.Options;
using Terra.Data.Entities.Identity;
using Terra.Data.Entities.Logging;
using Terra.Data.Repository.Identity;
using Terra.Data.Repository.Logging;
using Terra.Data.UnitOfWork;
using Terra.Service.Common.Base;
using Terra.Service.Identity.DTOs;
using Terra.Service.Identity.Interfaces;
using Terra.Core.Infrastructure.Email.Interfaces;
using Terra.Core.Infrastructure.SMS.Interfaces;
using Terra.Core.Common.Enums.Identity;
using Terra.Core.Configuration.Options;
using Terra.Core.Constants;

namespace Terra.Service.Identity.Implementations;

/// <summary>
/// 认证服务实现类
/// </summary>
/// <remarks>
/// 该服务提供以下功能：
/// <list type="bullet">
/// <item><description>用户凭据验证</description></item>
/// <item><description>JWT 访问令牌生成</description></item>
/// <item><description>刷新令牌管理</description></item>
/// <item><description>用户会话控制</description></item>
/// </list>
/// <para>
/// 安全特性：
/// <list type="bullet">
/// <item><description>使用 PBKDF2 进行密码哈希</description></item>
/// <item><description>基于 JWT 的无状态认证</description></item>
/// <item><description>支持令牌刷新机制</description></item>
/// <item><description>支持会话撤销</description></item>
/// </list>
/// </para>
/// </remarks>
public class AuthService : AppServiceBase, IAuthService
{
    private readonly IUserRepository _userRepository;
    private readonly IRefreshTokenRepository _refreshTokenRepository;
    private readonly ILoginLogRepository _loginLogRepository;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly JwtOptions _jwtOptions;
    private readonly JwtSecurityTokenHandler _tokenHandler;
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<AuthService> _logger;
    private readonly IEmailSender _emailSender;
    private readonly ISmsSender _smsSender;
    private readonly IPasswordResetTokenRepository _passwordResetTokenRepository;
    private readonly AuthSettings _authSettings;
    private readonly IPermissionRepository _permissionRepository;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="unitOfWork">工作单元</param>
    /// <param name="mapper">对象映射器</param>
    /// <param name="userRepository">用户仓储</param>
    /// <param name="refreshTokenRepository">刷新令牌仓储</param>
    /// <param name="loginLogRepository">登录日志仓储</param>
    /// <param name="httpContextAccessor">HTTP上下文访问器</param>
    /// <param name="jwtOptions">JWT配置选项</param>
    /// <param name="logger"></param>
    /// <param name="emailSender">电子邮件发送器</param>
    /// <param name="smsSender">短信发送器</param>
    /// <param name="passwordResetTokenRepository">密码重置令牌仓储</param>
    /// <param name="authSettings">认证设置</param>
    /// <param name="permissionRepository">权限仓储</param>
    public AuthService(
        IUnitOfWork unitOfWork,
        IMapper mapper,
        IUserRepository userRepository,
        IRefreshTokenRepository refreshTokenRepository,
        ILoginLogRepository loginLogRepository,
        IHttpContextAccessor httpContextAccessor,
        IOptions<JwtOptions> jwtOptions,
        ILogger<AuthService> logger,
        IEmailSender emailSender,
        ISmsSender smsSender,
        IPasswordResetTokenRepository passwordResetTokenRepository,
        IOptions<AuthSettings> authSettings,
        IPermissionRepository permissionRepository) : base(unitOfWork, mapper)
    {
        _unitOfWork = unitOfWork;
        _userRepository = userRepository;
        _refreshTokenRepository = refreshTokenRepository;
        _loginLogRepository = loginLogRepository;
        _httpContextAccessor = httpContextAccessor;
        _jwtOptions = jwtOptions.Value;
        _tokenHandler = new JwtSecurityTokenHandler();
        _logger = logger;
        _emailSender = emailSender;
        _smsSender = smsSender;
        _passwordResetTokenRepository = passwordResetTokenRepository;
        _authSettings = authSettings.Value;
        _permissionRepository = permissionRepository;
    }

    /// <summary>
    /// 验证用户凭据并生成Claims
    /// </summary>
    /// <param name="username">用户名/邮箱/手机号</param>
    /// <param name="password">密码</param>
    /// <returns>
    /// 元组包含：
    /// <list type="bullet">
    /// <item><description>success: 验证是否成功</description></item>
    /// <item><description>message: 验证结果消息</description></item>
    /// <item><description>principal: 验证通过的用户身份信息</description></item>
    /// </list>
    /// </returns>
    /// <remarks>
    /// 验证流程：
    /// <list type="number">
    /// <item><description>查找用户（支持用户名、邮箱、手机号登录）</description></item>
    /// <item><description>检查账号状态（是否锁定）</description></item>
    /// <item><description>验证密码</description></item>
    /// <item><description>生成身份信息（包含用户ID、用户名、邮箱等）</description></item>
    /// </list>
    /// </remarks>
    public async Task<(bool success, string message, ClaimsPrincipal principal)> ValidateCredentialsAsync(
        string username,
        string password)
    {
        var user = await _userRepository.FindByUsernameOrEmailOrPhoneAsync(username);
        if (user == null)
        {
            return (false, "用户名不存在", null);
        }

        // TODO: 实现账号锁定逻辑
        // if (user.IsLocked)
        // {
        //     return (false, "账号已被锁定", null);
        // }

        if (!_userRepository.ValidatePassword(user, password))
        {
            return (false, "用户名或密码错误", null);
        }

        // 构建基本Claims
        var claims = new List<Claim>
        {
            new(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new(ClaimTypes.Name, user.UserName),
            new(ClaimTypes.Email, user.Email ?? string.Empty),
            new(ClaimTypes.MobilePhone, user.PhoneNumber ?? string.Empty)
        };

        // 获取用户角色
        var roles = await _userRepository.GetRolesAsync(user.Id);
        foreach (var role in roles)
        {
            claims.Add(new Claim(ClaimTypes.Role, role.Name));

            // 添加超级管理员标记
            if (role.Name == SecurityConstants.SuperAdminRoleCode)
            {
                claims.Add(new Claim("is_superadmin", "true"));
            }
        }

        // 获取用户权限
        var permissions = await _permissionRepository.GetUserPermissionCodesAsync(user.Id);
        foreach (var permission in permissions)
        {
            claims.Add(new Claim(SecurityConstants.PermissionClaimType, permission));
        }

        var identity = new ClaimsIdentity(claims, "JWT");
        var principal = new ClaimsPrincipal(identity);

        return (true, "验证成功", principal);
    }

    /// <summary>
    /// 生成访问令牌和刷新令牌
    /// </summary>
    /// <param name="principal">用户身份信息</param>
    /// <returns>
    /// 元组包含：
    /// <list type="bullet">
    /// <item><description>accessToken: 访问令牌，用于API访问</description></item>
    /// <item><description>refreshToken: 刷新令牌，用于获取新的访问令牌</description></item>
    /// </list>
    /// </returns>
    /// <remarks>
    /// 生成流程：
    /// <list type="number">
    /// <item><description>使用用户信息生成JWT访问令牌</description></item>
    /// <item><description>生成随机刷新令牌</description></item>
    /// <item><description>保存刷新令牌到数据库</description></item>
    /// </list>
    /// </remarks>
    public async Task<(string accessToken, string refreshToken)> GenerateTokensAsync(ClaimsPrincipal principal)
    {
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtOptions.SecretKey));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        // 确保使用标准的Claim类型
        var claims = new List<Claim>();
        var existingClaims = principal.Claims.ToList();

        // 添加标准声明
        var nameId = existingClaims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
        var name = existingClaims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;
        var email = existingClaims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
        var phone = existingClaims.FirstOrDefault(c => c.Type == ClaimTypes.MobilePhone)?.Value;

        claims.Add(new Claim(JwtRegisteredClaimNames.Sub, nameId));
        claims.Add(new Claim(JwtRegisteredClaimNames.UniqueName, name));
        if (!string.IsNullOrEmpty(email))
            claims.Add(new Claim(JwtRegisteredClaimNames.Email, email));
        if (!string.IsNullOrEmpty(phone))
            claims.Add(new Claim("phone_number", phone));

        // 添加角色声明
        var roles = existingClaims.Where(c => c.Type == ClaimTypes.Role);
        foreach (var role in roles)
        {
            claims.Add(new Claim(ClaimTypes.Role, role.Value));
        }

        // 添加超级管理员标记
        var isSuperAdmin = existingClaims.FirstOrDefault(c => c.Type == "is_superadmin");
        if (isSuperAdmin != null)
        {
            claims.Add(new Claim("is_superadmin", isSuperAdmin.Value));
        }

        // 添加权限声明
        var permissions = existingClaims.Where(c => c.Type == SecurityConstants.PermissionClaimType);
        foreach (var permission in permissions)
        {
            claims.Add(new Claim(SecurityConstants.PermissionClaimType, permission.Value));
        }

        // 添加JWT标准声明
        claims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
        claims.Add(new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()));

        var now = DateTime.UtcNow;
        var expires = now.AddMinutes(_jwtOptions.ExpirationMinutes);

        var token = new JwtSecurityToken(
            issuer: _jwtOptions.Issuer,
            audience: _jwtOptions.Audience,
            claims: claims,
            notBefore: now,
            expires: expires,
            signingCredentials: credentials);

        var accessToken = _tokenHandler.WriteToken(token);
        var refreshToken = GenerateRefreshToken();

        // 保存刷新令牌
        var userId = Guid.Parse(nameId);
        await SaveRefreshTokenAsync(userId, refreshToken);

        return (accessToken, refreshToken);
    }

    /// <summary>
    /// 刷新访问令牌
    /// </summary>
    /// <param name="accessToken">过期的访问令牌</param>
    /// <param name="refreshToken">刷新令牌</param>
    /// <returns>
    /// 元组包含：
    /// <list type="bullet">
    /// <item><description>success: 刷新是否成功</description></item>
    /// <item><description>message: 刷新结果消息</description></item>
    /// <item><description>accessToken: 新的访问令牌</description></item>
    /// <item><description>refreshToken: 新的刷新令牌</description></item>
    /// </list>
    /// </returns>
    /// <remarks>
    /// 刷新流程：
    /// <list type="number">
    /// <item><description>验证访问令牌的签名（忽略过期时间）</description></item>
    /// <item><description>验证刷新令牌的有效性</description></item>
    /// <item><description>检查刷新令牌是否已使用或已撤销</description></item>
    /// <item><description>生成新的令牌对</description></item>
    /// <item><description>标记旧的刷新令牌为已使用</description></item>
    /// </list>
    /// </remarks>
    public async Task<(bool success, string message, string accessToken, string refreshToken)> RefreshTokenAsync(
        string accessToken,
        string refreshToken)
    {
        try
        {
            // 验证访问令牌
            var principal = _tokenHandler.ValidateToken(
                accessToken,
                new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtOptions.SecretKey)),
                    ValidateIssuer = true,
                    ValidIssuer = _jwtOptions.Issuer,
                    ValidateAudience = true,
                    ValidAudience = _jwtOptions.Audience,
                    ValidateLifetime = false // 不验证过期时间
                },
                out var validatedToken);

            // 验证刷新令牌
            var storedToken = await _refreshTokenRepository.FindByTokenAsync(refreshToken);
            if (storedToken == null)
            {
                return (false, "无效的刷新令牌", null, null);
            }

            if (storedToken.IsRevoked)
            {
                return (false, "刷新令牌已被撤销", null, null);
            }

            if (storedToken.IsUsed)
            {
                return (false, "刷新令牌已被使用", null, null);
            }

            if (DateTime.UtcNow > storedToken.ExpiresAt)
            {
                return (false, "刷新令牌已过期", null, null);
            }

            // 标记当前刷新令牌为已使用
            storedToken.IsUsed = true;
            await _refreshTokenRepository.UpdateAsync(storedToken);

            // 生成新的令牌对
            var (newAccessToken, newRefreshToken) = await GenerateTokensAsync(principal);

            return (true, "令牌刷新成功", newAccessToken, newRefreshToken);
        }
        catch (Exception ex)
        {
            return (false, $"令牌刷新失败: {ex.Message}", null, null);
        }
    }

    /// <summary>
    /// 撤销刷新令牌
    /// </summary>
    /// <param name="refreshToken">要撤销的刷新令牌</param>
    /// <remarks>
    /// 撤销后的令牌将无法用于刷新访问令牌，用户需要重新登录。
    /// 此方法通常用于：
    /// <list type="bullet">
    /// <item><description>用户主动登出</description></item>
    /// <item><description>检测到安全威胁时</description></item>
    /// <item><description>管理员强制用户下线</description></item>
    /// </list>
    /// </remarks>
    public async Task RevokeRefreshTokenAsync(string refreshToken)
    {
        await _refreshTokenRepository.RevokeAsync(refreshToken);
    }

    /// <summary>
    /// 注销用户
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <remarks>
    /// 注销流程：
    /// <list type="number">
    /// <item><description>撤销用户的所有刷新令牌</description></item>
    /// <item><description>清除用户的会话信息</description></item>
    /// <item><description>强制用户在所有设备上登出</description></item>
    /// </list>
    /// </remarks>
    public async Task<ApiResponse> LogoutAsync(Guid userId)
    {
        await _refreshTokenRepository.RevokeAllAsync(userId);

        // 获取用户信息
        var user = await _userRepository.GetByIdAsync(userId);
        if (user != null)
        {
            // 记录登出日志
            await CreateLoginLogAsync(user.UserName, true, "Password", "用户登出", 2);
        }

        return ApiResponse.Success("登出成功");
    }

    /// <summary>
    /// 生成随机刷新令牌
    /// </summary>
    /// <returns>Base64编码的刷新令牌字符串</returns>
    private string GenerateRefreshToken()
    {
        var randomNumber = new byte[64];
        using var rng = RandomNumberGenerator.Create();
        rng.GetBytes(randomNumber);
        return Convert.ToBase64String(randomNumber);
    }

    /// <summary>
    /// 保存刷新令牌到数据库
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="token">刷新令牌值</param>
    /// <remarks>
    /// 保存时会设置：
    /// <list type="bullet">
    /// <item><description>过期时间</description></item>
    /// <item><description>使用状态</description></item>
    /// <item><description>撤销状态</description></item>
    /// </list>
    /// </remarks>
    private async Task SaveRefreshTokenAsync(Guid userId, string token)
    {
        var refreshToken = new RefreshToken
        {
            UserId = userId,
            Token = token,
            ExpiresAt = DateTime.UtcNow.AddDays(_jwtOptions.RefreshTokenExpirationDays),
            IsUsed = false,
            IsRevoked = false
        };

        await _refreshTokenRepository.InsertAsync(refreshToken);
    }

    /// <summary>
    /// 用户登录
    /// </summary>
    public async Task<ApiResponse<LoginResponseDto>> LoginAsync(LoginRequestDto request)
    {
        var (success, message, principal) = await ValidateCredentialsAsync(
            request.Username,
            request.Password);

        if (!success)
        {
            // 记录登录失败日志
            await CreateLoginLogAsync(request.Username, false, "Password", message);
            return ApiResponse<LoginResponseDto>.Error(SecurityErrorCodes.LoginFailed, message);
        }

        var (accessToken, refreshToken) = await GenerateTokensAsync(principal);
        var userId = Guid.Parse(principal.FindFirst(ClaimTypes.NameIdentifier)?.Value);
        var user = await _userRepository.GetByIdAsync(userId);

        // 记录登录成功日志
        await CreateLoginLogAsync(user.UserName, true, "Password", "登录成功");

        var response = new LoginResponseDto
        {
            AccessToken = $"{accessToken}",
            RefreshToken = refreshToken,
            ExpiresAt = DateTime.UtcNow.AddMinutes(_jwtOptions.ExpirationMinutes),
            User = new UserDto
            {
                Id = user.Id,
                UserName = user.UserName,
                Email = user.Email,
                PhoneNumber = user.PhoneNumber
            }
        };

        return ApiResponse<LoginResponseDto>.Success(response);
    }

    /// <summary>
    /// 验证用户身份并获取用户信息
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns>用户信息</returns>
    public async Task<ApiResponse<UserDto>> GetUserInfoAsync(Guid userId)
    {
        // 验证用户是否存在
        var user = await _userRepository.GetByIdAsync(userId);
        if (user == null)
        {
            return ApiResponse<UserDto>.Error(SecurityErrorCodes.UserNotFound);
        }

        // 验证用户状态
        if (user.IsDeleted)
        {
            return ApiResponse<UserDto>.Error(SecurityErrorCodes.Unauthorized);
        }

        if (user.LockoutEnabled && user.LockoutEnd.HasValue && user.LockoutEnd.Value > DateTime.UtcNow)
        {
            return ApiResponse<UserDto>.Error(SecurityErrorCodes.AccountLocked);
        }

        var userDto = new UserDto
        {
            Id = user.Id,
            UserName = user.UserName,
            Email = user.Email,
            PhoneNumber = user.PhoneNumber,
            // TODO:增加用户真实姓名字段
            RealName = ""
        };

        return ApiResponse<UserDto>.Success(userDto);
    }

    /// <summary>
    /// 刷新访问令牌
    /// </summary>
    public async Task<ApiResponse<TokenResponseDto>> RefreshTokenAsync(RefreshTokenRequestDto request)
    {
        try
        {
            // 验证访问令牌
            var principal = _tokenHandler.ValidateToken(
                request.AccessToken.Replace("Bearer ", ""),
                new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtOptions.SecretKey)),
                    ValidateIssuer = true,
                    ValidIssuer = _jwtOptions.Issuer,
                    ValidateAudience = true,
                    ValidAudience = _jwtOptions.Audience,
                    ValidateLifetime = false // 不验证过期时间
                },
                out var validatedToken);

            // 验证刷新令牌
            var storedToken = await _refreshTokenRepository.FindByTokenAsync(request.RefreshToken);
            if (storedToken == null)
            {
                return ApiResponse<TokenResponseDto>.Error(SecurityErrorCodes.InvalidRefreshToken);
            }

            if (storedToken.IsRevoked)
            {
                return ApiResponse<TokenResponseDto>.Error(SecurityErrorCodes.RefreshTokenRevoked);
            }

            if (storedToken.IsUsed)
            {
                return ApiResponse<TokenResponseDto>.Error(SecurityErrorCodes.RefreshTokenUsed);
            }

            if (DateTime.UtcNow > storedToken.ExpiresAt)
            {
                return ApiResponse<TokenResponseDto>.Error(SecurityErrorCodes.RefreshTokenExpired);
            }

            // 标记当前刷新令牌为已使用
            storedToken.IsUsed = true;
            await _refreshTokenRepository.UpdateAsync(storedToken);

            // 生成新的令牌对
            var (accessToken, refreshToken) = await GenerateTokensAsync(principal);

            var response = new TokenResponseDto
            {
                Data = $"{accessToken}",
                RefreshToken = refreshToken,
                Status = 200
            };

            return ApiResponse<TokenResponseDto>.Success(response);
        }
        catch (Exception ex)
        {
            return ApiResponse<TokenResponseDto>.Error(SecurityErrorCodes.RefreshTokenFailed, ex.Message);
        }
    }

    /// <summary>
    /// 修改密码
    /// </summary>
    public async Task<ApiResponse<object>> ChangePasswordAsync(Guid userId, ChangePasswordRequestDto request)
    {
        var user = await _userRepository.GetByIdAsync(userId);
        if (user == null)
        {
            return ApiResponse.Error(SecurityErrorCodes.UserNotFound);
        }

        try
        {
            await _userRepository.ChangePasswordAsync(user, request.CurrentPassword, request.NewPassword);

            // 修改密码后，登出所有设备
            await LogoutAsync(userId);

            return ApiResponse.Success("密码修改成功");
        }
        catch (InvalidOperationException ex)
        {
            return ApiResponse.Error(SecurityErrorCodes.ChangePasswordFailed, ex.Message);
        }
    }

    /// <summary>
    /// 用户注册
    /// </summary>
    public async Task<ApiResponse<RegisterResponseDto>> RegisterAsync(RegisterRequestDto request)
    {
        // 验证用户名是否已存在
        if (await _userRepository.ExistsByUsernameAsync(request.UserName))
        {
            return ApiResponse<RegisterResponseDto>.Error(SecurityErrorCodes.UserNameAlreadyExists);
        }

        // 如果提供了邮箱，验证邮箱是否已存在
        if (!string.IsNullOrEmpty(request.Email) &&
            await _userRepository.ExistsByEmailAsync(request.Email))
        {
            return ApiResponse<RegisterResponseDto>.Error(SecurityErrorCodes.EmailAlreadyExists);
        }

        // 如果提供了手机号，验证手机号是否已存在
        if (!string.IsNullOrEmpty(request.PhoneNumber) &&
            await _userRepository.ExistsByPhoneNumberAsync(request.PhoneNumber))
        {
            return ApiResponse<RegisterResponseDto>.Error(SecurityErrorCodes.PhoneNumberAlreadyExists);
        }

        try
        {
            // 创建用户实体
            var user = new User
            {
                UserName = request.UserName,
                NormalizedUserName = request.UserName.ToUpperInvariant(),
                Email = request.Email,
                NormalizedEmail = request.Email?.ToUpperInvariant(),
                PhoneNumber = request.PhoneNumber,
                EmailConfirmed = false,
                PhoneNumberConfirmed = false,
                TwoFactorEnabled = false,
                LockoutEnabled = true,
                AccessFailedCount = 0
            };

            // 设置密码
            await _userRepository.SetPasswordAsync(user, request.Password);

            // 保存用户
            await _userRepository.InsertAsync(user);
            await _unitOfWork.SaveChangesAsync();

            // 生成身份信息
            var claims = new List<Claim>
            {
                new(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new(ClaimTypes.Name, user.UserName)
            };

            // 如果有邮箱，添加邮箱声明
            if (!string.IsNullOrEmpty(user.Email))
            {
                claims.Add(new Claim(ClaimTypes.Email, user.Email));
            }

            // 如果有手机号，添加手机号声明
            if (!string.IsNullOrEmpty(user.PhoneNumber))
            {
                claims.Add(new Claim(ClaimTypes.MobilePhone, user.PhoneNumber));
            }

            var identity = new ClaimsIdentity(claims, "JWT");
            var principal = new ClaimsPrincipal(identity);

            // 生成令牌
            var (accessToken, refreshToken) = await GenerateTokensAsync(principal);

            // 构建响应
            var response = new RegisterResponseDto
            {
                User = new UserDto
                {
                    Id = user.Id,
                    UserName = user.UserName,
                    Email = user.Email,
                    PhoneNumber = user.PhoneNumber
                },
                AccessToken = $"Bearer {accessToken}",
                RefreshToken = refreshToken,
                ExpiresAt = DateTime.UtcNow.AddMinutes(_jwtOptions.ExpirationMinutes)
            };

            return ApiResponse<RegisterResponseDto>.Success(response);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "用户注册失败");
            return ApiResponse<RegisterResponseDto>.Error(SecurityErrorCodes.RegistrationFailed);
        }
    }

    /// <summary>
    /// 创建登录日志
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <param name="status">状态</param>
    /// <param name="loginMethod">登录方式</param>
    /// <param name="message">消息</param>
    /// <param name="type">操作类型：1登录 2登出</param>
    /// <returns>创建的日志记录</returns>
    private async Task CreateLoginLogAsync(
        string userName,
        bool status,
        string loginMethod,
        string message,
        int type = 1)
    {
        var context = _httpContextAccessor.HttpContext;
        var (browser, os) = HttpContextUtils.GetClientInfo(context);

        var log = new LoginLog
        {
            Level = status ? "Information" : "Warning", // 登录成功为 Information，失败为 Warning
            UserName = userName,
            LoginTime = DateTime.UtcNow,
            Status = status,
            LoginMethod = loginMethod,
            ErrorMessage = message,
            IpAddress = HttpContextUtils.GetClientIpAddress(context),
            Browser = browser,
            OS = os
        };

        await _loginLogRepository.InsertAsync(log);
    }

    #region 密码重置
    /// <summary>
    /// 发起密码重置
    /// </summary>
    public async Task<ApiResponse> InitiatePasswordResetAsync(string account, ResetType resetType, string operatorId = null)
    {
        try
        {
            // 1. 查找用户
            var user = await _userRepository.FindByUsernameOrEmailOrPhoneAsync(account);
            if (user == null)
            {
                return ApiResponse.Error(SecurityErrorCodes.UserNotFound, "用户不存在");
            }

            // 2. 生成重置令牌
            var token = await GeneratePasswordResetTokenAsync(user);

            // 3. 根据重置类型发送通知
            bool notificationSent = false;
            string errorMessage = null;

            switch (resetType)
            {
                case ResetType.Email:
                    if (string.IsNullOrEmpty(user.Email))
                    {
                        return ApiResponse.Error(SecurityErrorCodes.EmailNotFound, "用户未设置邮箱");
                    }

                    var (emailSent, emailError) = await SendPasswordResetEmailAsync(user.Email, token);
                    notificationSent = emailSent;
                    errorMessage = emailError;
                    break;

                case ResetType.Sms:
                    if (string.IsNullOrEmpty(user.PhoneNumber))
                    {
                        return ApiResponse.Error(SecurityErrorCodes.PhoneNotFound, "用户未设置手机号");
                    }

                    var (smsSent, smsError) = await SendPasswordResetSmsAsync(user.PhoneNumber, token);
                    notificationSent = smsSent;
                    errorMessage = smsError;
                    break;

                default:
                    return ApiResponse.Error(SecurityErrorCodes.InvalidResetType, "无效的重置方式");
            }

            // 检查发送结果
            if (!notificationSent)
            {
                var errorCode = resetType == ResetType.Email
                    ? SecurityErrorCodes.EmailSendFailed
                    : SecurityErrorCodes.SmsSendFailed;

                return ApiResponse.Error(errorCode, errorMessage);
            }

            // 4. TODO: 实现密码重置日志记录

            return ApiResponse.Success("密码重置请求已发送");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "密码重置请求失败");
            return ApiResponse.Error(SecurityErrorCodes.PasswordResetFailed, "密码重置请求失败");
        }
    }

    /// <summary>
    /// 生成密码重置令牌
    /// </summary>
    private async Task<string> GeneratePasswordResetTokenAsync(User user)
    {
        // 生成随机令牌
        var tokenBytes = new byte[32];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(tokenBytes);
        }
        var token = Convert.ToBase64String(tokenBytes);

        // 保存令牌到数据库
        var resetToken = new PasswordResetToken
        {
            UserId = user.Id,
            Token = token,
            CreatedTime = DateTime.UtcNow,
            ExpiresTime = DateTime.UtcNow.AddMinutes(15), // 15分钟过期
            IsUsed = false
        };

        await _passwordResetTokenRepository.InsertAsync(resetToken);
        await _unitOfWork.SaveChangesAsync();

        return token;
    }

    /// <summary>
    /// 发送密码重置邮件
    /// </summary>
    /// <returns>发送结果，包含成功/失败状态和错误信息</returns>
    private async Task<(bool success, string errorMessage)> SendPasswordResetEmailAsync(string email, string token)
    {
        var resetLink = GeneratePasswordResetLink(token);
        var subject = "密码重置请求";
        var body = $@"
            <h2>密码重置请求</h2>
            <p>您收到此邮件是因为有人请求重置您的密码。如果这不是您本人的操作，请忽略此邮件。</p>
            <p>点击以下链接重置密码：</p>
            <p><a href='{resetLink}'>{resetLink}</a></p>
            <p>此链接将在15分钟后失效。</p>";

        var sendResult = await _emailSender.SendAsync(email, subject, body, true);
        if (!sendResult)
        {
            _logger.LogError("发送密码重置邮件失败，收件人: {Email}", email);
            return (false, "发送邮件失败，请检查邮箱地址是否正确或稍后再试");
        }

        return (true, null);
    }

    /// <summary>
    /// 发送密码重置短信
    /// </summary>
    /// <returns>发送结果，包含成功/失败状态和错误信息</returns>
    private async Task<(bool success, string errorMessage)> SendPasswordResetSmsAsync(string phoneNumber, string token)
    {
        var message = $"您的密码重置验证码是：{token.Substring(0, 6)}，请在5分钟内完成重置操作。";

        var sendResult = await _smsSender.SendAsync(phoneNumber, message);
        if (!sendResult)
        {
            _logger.LogError("发送密码重置短信失败，手机号: {PhoneNumber}", phoneNumber);
            return (false, "发送短信失败，请检查手机号是否正确或稍后再试");
        }

        return (true, null);
    }

    /// <summary>
    /// 验证并重置密码
    /// </summary>
    /// <param name="token">验证token/验证码</param>
    /// <param name="newPassword">新密码</param>
    /// <param name="resetType">重置方式</param>
    /// <returns>操作结果</returns>
    public async Task<ApiResponse> ValidateAndResetPasswordAsync(string token, string newPassword, ResetType resetType)
    {
        try
        {
            token = token.FromUrlSafeBase64();
            // 验证令牌有效性
            var (succeeded, userId) = await _userRepository.VerifyPasswordResetTokenAsync(token);
            if (!succeeded)
            {
                return ApiResponse.Error(SecurityErrorCodes.InvalidResetToken);
            }

            var user = await _userRepository.GetByIdAsync(userId);
            if (user == null)
            {
                return ApiResponse.Error(SecurityErrorCodes.UserNotFound);
            }

            // 验证密码强度
            if (!ValidationUtils.ValidatePasswordStrength(newPassword))
            {
                return ApiResponse.Error(
                    SecurityErrorCodes.PasswordStrengthInsufficient,
                    "密码必须至少8位，包含大小写字母、数字和特殊字符");
            }

            // 重置密码
            var resetResult = await _userRepository.ResetPasswordAsync(user, token, newPassword);
            if (!resetResult.Succeeded)
            {
                return ApiResponse.Error(SecurityErrorCodes.PasswordResetFailed);
            }

            // 记录密码重置成功
            _logger.LogInformation("Password reset successful for user {UserId}", userId);

            return ApiResponse.Success();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Password reset failed");
            return ApiResponse.Error(SecurityErrorCodes.PasswordResetFailed);
        }
    }
    #endregion

    /// <summary>
    /// 检查密码状态
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns>密码状态检查结果</returns>
    public async Task<ApiResponse<PwdResetDtos>> CheckPasswordStatusAsync(string userId)
    {
        try
        {
            var user = await _userRepository.GetByIdAsync(Guid.Parse(userId));
            if (user == null)
            {
                return ApiResponse<PwdResetDtos>.Error(SecurityErrorCodes.UserNotFound);
            }

            var hasPassword = await _userRepository.HasPasswordAsync(user);
            if (!hasPassword)
            {
                return ApiResponse<PwdResetDtos>.Success(new PwdResetDtos
                {
                    NeedReset = true,
                    ResetType = PasswordResetType.InitialPassword,
                    Message = "需要设置初始密码"
                });
            }

            if (user.RequiresPasswordReset)
            {
                return ApiResponse<PwdResetDtos>.Success(new PwdResetDtos
                {
                    NeedReset = true,
                    ResetType = PasswordResetType.ForceChange,
                    Message = "需要强制修改密码"
                });
            }

            // 检查密码是否过期
            if (user.LastPasswordChangedTime.HasValue &&
                (DateTime.UtcNow - user.LastPasswordChangedTime.Value).TotalDays > 90)
            {
                return ApiResponse<PwdResetDtos>.Success(new PwdResetDtos
                {
                    NeedReset = true,
                    ResetType = PasswordResetType.Expired,
                    Message = "密码已过期"
                });
            }

            return ApiResponse<PwdResetDtos>.Success(new PwdResetDtos
            {
                NeedReset = false,
                ResetType = PasswordResetType.None,
                Message = "密码状态正常"
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Check password status failed");
            return ApiResponse<PwdResetDtos>.Error(SecurityErrorCodes.UnauthorizedOperation);
        }
    }

    /// <summary>
    /// 重置初始密码
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="currentPassword">当前密码</param>
    /// <param name="newPassword">新密码</param>
    /// <returns>操作结果</returns>
    public async Task<ApiResponse> ResetInitialPasswordAsync(string userId, string currentPassword, string newPassword)
    {
        try
        {
            var user = await _userRepository.GetByIdAsync(Guid.Parse(userId));
            if (user == null)
            {
                return ApiResponse.Error(SecurityErrorCodes.UserNotFound);
            }

            // 验证当前密码
            if (!await _userRepository.CheckPasswordAsync(user, currentPassword))
            {
                return ApiResponse.Error(SecurityErrorCodes.InvalidCredentials);
            }

            // TODO: 验证密码强度


            // 更改密码
            var changePasswordResult = await _userRepository.ChangePasswordAsync(user, currentPassword, newPassword);
            if (!changePasswordResult.Succeeded)
            {
                return ApiResponse.Error(SecurityErrorCodes.PasswordResetFailed);
            }

            // 更新密码状态
            user.RequiresPasswordReset = false;
            user.LastPasswordChangedTime = DateTime.UtcNow;
            await _userRepository.UpdateAsync(user);

            // 记录密码重置成功
            _logger.LogInformation("Initial password reset successful for user {UserId}", userId);

            return ApiResponse.Success();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Initial password reset failed");
            return ApiResponse.Error(SecurityErrorCodes.PasswordResetFailed);
        }
    }

    private string GeneratePasswordResetLink(string token)
    {
        // 使用URL安全的Base64编码处理token
        string urlSafeToken = token.ToUrlSafeBase64();
        return $"{_authSettings.PasswordReset.BaseUrl.TrimEnd('/')}{_authSettings.PasswordReset.TokenPath}?token={urlSafeToken}";
    }
}